package com.keyue.common.utils;

import com.keyue.common.constant.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @param
 * @author 邓彬
 * @version 0.1.0
 * @Description
 * @return
 * @date 2021/4/16 17:44
 * @since 0.1.0
 */
@Slf4j
public class StringUtils {
    /**
     * 首字母变小写
     *
     * @param str
     * @return
     */
    public static String firstCharToLowerCase(String str) {
        char firstChar = str.charAt(0);
        if (firstChar >= 'A' && firstChar <= 'Z') {
            char[] arr = str.toCharArray();
            arr[0] += ('a' - 'A');
            return new String(arr);
        }
        return str;
    }

    /**
     * 首字母变大写
     *
     * @param str
     * @return
     */
    public static String firstCharToUpperCase(String str) {
        char firstChar = str.charAt(0);
        if (firstChar >= 'a' && firstChar <= 'z') {
            char[] arr = str.toCharArray();
            arr[0] -= ('a' - 'A');
            return new String(arr);
        }
        return str;
    }

    /**
     * 判断是否为空
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(final String str) {
        return (str == null) || (str.length() == 0);
    }

    /**
     * 判断是否不为空
     *
     * @param str
     * @return
     */
    public static boolean isNotEmpty(final String str) {
        return !isEmpty(str);
    }

    /**
     * 判断是否空白
     *
     * @param str
     * @return
     */
    public static boolean isBlank(final String str) {
        int strLen;
        if ((str == null) || ((strLen = str.length()) == 0)) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是否不是空白
     *
     * @param str
     * @return
     */
    public static boolean isNotBlank(final String str) {
        return !isBlank(str);
    }

    /**
     * 判断多个字符串全部是否为空
     *
     * @param strings
     * @return
     */
    public static boolean isAllEmpty(String... strings) {
        if (strings == null) {
            return true;
        }
        for (String str : strings) {
            if (isNotEmpty(str)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断多个字符串其中任意一个是否为空
     *
     * @param strings
     * @return
     */
    public static boolean isHasEmpty(String... strings) {
        if (strings == null) {
            return true;
        }
        for (String str : strings) {
            if (isEmpty(str)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断多个字符串是否都为blank
     *
     * @param strings
     * @return
     */
    public static boolean isAllBlank(String... strings) {
        if (strings == null) {
            return true;
        }
        for (String str : strings) {
            if (isNotBlank(str)) {
                return false;
            }
        }
        return true;
    }

    /**
     * checkValue为 null 或者为 "" 时返回 defaultValue
     *
     * @param checkValue
     * @param defaultValue
     * @return
     */
    public static String isEmpty(String checkValue, String defaultValue) {
        return isEmpty(checkValue) ? defaultValue : checkValue;
    }

    /**
     * 字符串不为 null 而且不为 "" 并且等于other
     *
     * @param str
     * @param other
     * @return
     */
    public static boolean isNotEmptyAndEqualsOther(String str, String other) {
        return !isEmpty(str) && str.equals(other);
    }

    /**
     * 字符串不为 null 而且不为 "" 并且不等于other
     *
     * @param str
     * @param other
     * @return
     */
    public static boolean isNotEmptyAndNotEqualsOther(String str, String... other) {
        if (isEmpty(str)) {
            return false;
        }
        for (String s : other) {
            if (str.equals(s)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 字符串不等于other
     *
     * @param str
     * @param other
     * @return
     */
    public static boolean isNotEqualsOther(String str, String... other) {
        for (String s : other) {
            if (s.equals(str)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断字符串不为空
     *
     * @param strings
     * @return
     */
    public static boolean isNotEmpty(String... strings) {
        if (strings == null || strings.length == 0) {
            return false;
        }
        for (String str : strings) {
            if (str == null || "".equals(str.trim())) {
                return false;
            }
        }
        return true;
    }

    /**
     * 比较字符相等
     *
     * @param value
     * @param equals
     * @return
     */
    public static boolean equals(String value, String equals) {
        if (isAllEmpty(value, equals)) {
            return true;
        }
        //进一步判断value是不是空，如果是空，要直接equals会报NPE异常
        if (value == null) {
            return false;
        }
        return value.equals(equals);
    }

    /**
     * @description 将字符串转换为数字数组
     * @author 黄楷涵
     * @date 2020/9/15
     */
    public static int[] stringParseToInt(String str, String regex) {
        return stringParseToInt(str.split(regex));
    }

    /**
     * @description 将字符串数组转换为数字数组
     * @author dengbin
     * @date 2020/9/15
     */
    public static int[] stringParseToInt(String[] str) {
        int[] num = new int[str.length];
        for (int i = 0; i < str.length; i++) {
            num[i] = Integer.parseInt(str[i]);
        }
        return num;
    }

    /**
     * 比较字符串不相等
     *
     * @param value
     * @param equals
     * @return
     */
    public static boolean isNotEquals(String value, String equals) {
        return !equals(value, equals);
    }

    public static String[] split(String content, String separatorChars) {
        return splitWorker(content, separatorChars, -1, false);
    }

    public static String[] split(String str, String separatorChars, int max) {
        return splitWorker(str, separatorChars, max, false);
    }

    public static final String[] EMPTY_STRING_ARRAY = new String[0];

    private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
        if (str == null) {
            return null;
        }
        int len = str.length();
        if (len == 0) {
            return EMPTY_STRING_ARRAY;
        }
        List<String> list = new ArrayList<String>();
        int sizePlus1 = 1;
        int i = 0, start = 0;
        boolean match = false;
        boolean lastMatch = false;
        if (separatorChars == null) {
            while (i < len) {
                if (Character.isWhitespace(str.charAt(i))) {
                    if (match || preserveAllTokens) {
                        lastMatch = true;
                        if (sizePlus1++ == max) {
                            i = len;
                            lastMatch = false;
                        }
                        list.add(str.substring(start, i));
                        match = false;
                    }
                    start = ++i;
                    continue;
                }
                lastMatch = false;
                match = true;
                i++;
            }
        } else if (separatorChars.length() == 1) {
            char sep = separatorChars.charAt(0);
            while (i < len) {
                if (str.charAt(i) == sep) {
                    if (match || preserveAllTokens) {
                        lastMatch = true;
                        if (sizePlus1++ == max) {
                            i = len;
                            lastMatch = false;
                        }
                        list.add(str.substring(start, i));
                        match = false;
                    }
                    start = ++i;
                    continue;
                }
                lastMatch = false;
                match = true;
                i++;
            }
        } else {
            while (i < len) {
                if (separatorChars.indexOf(str.charAt(i)) >= 0) {
                    if (match || preserveAllTokens) {
                        lastMatch = true;
                        if (sizePlus1++ == max) {
                            i = len;
                            lastMatch = false;
                        }
                        list.add(str.substring(start, i));
                        match = false;
                    }
                    start = ++i;
                    continue;
                }
                lastMatch = false;
                match = true;
                i++;
            }
        }
        if (match || (preserveAllTokens && lastMatch)) {
            list.add(str.substring(start, i));
        }
        return list.toArray(EMPTY_STRING_ARRAY);
    }

    /**
     * 消除转义字符
     *
     * @param str
     * @return
     */
    public static String escapeXml(String str) {
        if (str == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); ++i) {
            char c = str.charAt(i);
            switch (c) {
                case '\u00FF':
                case '\u0024':
                    break;
                case '&':
                    sb.append("&amp;");
                    break;
                case '<':
                    sb.append("&lt;");
                    break;
                case '>':
                    sb.append("&gt;");
                    break;
                case '\"':
                    sb.append("&quot;");
                    break;
                case '\'':
                    sb.append("&apos;");
                    break;
                default:
                    if (c <= '\u001F') {
                        break;
                    }
                    if (c >= '\uE000' && c <= '\uF8FF') {
                        break;
                    }
                    if (c >= '\uFFF0') {
                        break;
                    }
                    sb.append(c);
                    break;
            }
        }
        return sb.toString();
    }

    /**
     * 将字符串中特定模式的字符转换成map中对应的值
     *
     * @param s   需要转换的字符串
     * @param map 转换所需的键值对集合
     * @return 转换后的字符串
     */
    public static String replace(String s, Map<String, Object> map) {
        StringBuilder ret = new StringBuilder((int) (s.length() * 1.5));
        int cursor = 0;
        for (int start, end; (start = s.indexOf("${", cursor)) != -1 && (end = s.indexOf("}", start)) != -1; ) {
            ret.append(s.substring(cursor, start)).append(map.get(s.substring(start + 2, end)));
            cursor = end + 1;
        }
        ret.append(s.substring(cursor, s.length()));
        return ret.toString();
    }

    public static String replace(String s, Object... objs) {
        if (objs == null || objs.length == 0) {
            return s;
        }
        if (!s.contains("{}")) {
            return s;
        }
        StringBuilder ret = new StringBuilder((int) (s.length() * 1.5));
        int cursor = 0;
        int index = 0;
        for (int start; (start = s.indexOf("{}", cursor)) != -1; ) {
            ret.append(s.substring(cursor, start));
            if (index < objs.length) {
                ret.append(objs[index]);
            } else {
                ret.append("{}");
            }
            cursor = start + 2;
            index++;
        }
        ret.append(s.substring(cursor, s.length()));
        return ret.toString();
    }


    /**
     * 转换为字节数组
     *
     * @param bytes
     * @return
     */
    public static String toString(byte[] bytes) {
        return new String(bytes, StandardCharsets.UTF_8);
    }

    /**
     * 转换为字节数组
     *
     * @param str
     * @return
     */
    public static byte[] getBytes(String str) {
        return str != null ? str.getBytes(StandardCharsets.UTF_8) : null;
    }

    public static boolean isNumeric(String cs) {
        if (isEmpty(cs)) {
            return false;
        }
        for (int i = 0, sz = cs.length(); i < sz; ++i) {
            if (!Character.isDigit(cs.charAt(i))) {
                return false;
            }
        }
        return true;

    }

    /**
     * 手机号脱敏
     *
     * @param phoneNumber
     * @return
     */
    public static String desensitizedPhoneNumber(String phoneNumber) {
        if (StringUtils.isNotEmpty(phoneNumber)) {
            phoneNumber = phoneNumber.replaceAll("(\\w{3})\\w*(\\w{4})", "$1****$2");
        }
        return phoneNumber;
    }

    /**
     * 校验3位小数
     *
     * @param str
     * @return
     */
    public static boolean checkDecimal(String str) {
        return Pattern.compile(Constant.DICMAL_REGEXP).matcher(str).find();
    }

    /**
     * 校验11位国内手机号
     * <p>规则: 11位数，首位必须为1，第二位可以是3-9；其他位数不限制
     *
     * @param phone 手机号
     * @return 格式正确则返回false; 反之为true
     * @author A80080
     * @createDate 2020/12/19
     */
    public static boolean checkPhoneNum(String phone) {
        return StringUtils.isEmpty(phone) || !Pattern.compile("^1([3-9])[0-9]{9}$").matcher(phone).find();
    }

    /**
     * @param str
     * @return boolean
     * @Description 判断字符串是否含有空格
     * @version 0.1.0
     * @author 邓彬
     * @date 2021/1/13 18:10
     * @since 0.1.0
     */
    public static boolean checkStringContainEmpty(String str) {
        return !StringUtils.isEmpty(str) && str.contains(" ");
    }

    /**
     * 字符串切分
     *
     * @param splitStr
     * @param splitFlag
     * @return
     */
    public static List<String> splitTag(String splitStr, String splitFlag) {
        return StringUtils.isBlank(splitStr) || StringUtils.isBlank(splitFlag) ?
                new ArrayList<>() :
                Arrays.stream(splitStr.split(splitFlag)).collect(Collectors.toList());
    }

    /**
     * @param name
     * @return true代表全是汉字
     * @Description 校验String是否全是中文
     * @version 0.1.0
     * @author 邓彬
     * @date 2021/1/18 19:54
     * @since 0.1.0
     */
    public static boolean checkNameChina(String name) {
        boolean res = true;
        char[] cTemp = name.toCharArray();
        for (int i = 0; i < name.length(); i++) {
            if (!isChinese(cTemp[i])) {
                res = false;
                break;
            }
        }
        return res;
    }

    /**
     * @param c
     * @return true代表是汉字
     * @Description 判定输入的是否是汉字
     * @version 0.1.0
     * @author 邓彬
     * @date 2021/1/18 19:53
     * @since 0.1.0
     */
    public static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }

    /**
     * @param c
     * @return true代表符合条件
     * @Description 校验某个字符是否是a-z、A-Z、_、0-9
     * @version 0.1.0
     * @author 邓彬
     * @date 2021/1/18 19:56
     * @since 0.1.0
     */
    public static boolean isWord(char c) {
        return Pattern.compile("[\\w]").matcher("" + c).matches();
    }

    /**
     * @param str
     * @return boolean
     * @Description 字符串是否仅包含数字和字母
     * @version 0.1.0
     * @author 邓彬
     * @date 2021/1/18 20:00
     * @since 0.1.0
     */
    public static boolean isLetterDigit(String str) {
        return str.matches("^[a-z0-9A-Z]+$");
    }

    /**
     * @param str
     * @return boolean
     * @Description 判断是否是纯数字
     * @version 0.1.0
     * @author 邓彬
     * @date 2021/1/23 16:33
     * @since 0.1.0
     */
    public static boolean isDigit(String str) {
        return str.matches("^[0-9]+$");
    }

    /**
     * 是否合法手机号
     *
     * @param phone
     * @return
     */
    public static boolean isMobilePhone(String phone) {
        return Pattern.compile(Constant.PHONE_REGEXP).matcher(phone).matches();
    }

    /**
     * 是否脱敏手机号
     *
     * @param phone
     * @return
     */
    public static boolean isDesensitizationMobilePhone(String phone) {
        return Pattern.compile(Constant.PHONE_DESENSITIZATION_REGEXP).matcher(phone).matches();
    }

    /**
     * 判断String是否是整数<br>
     * 支持10进制
     *
     * @param s String
     * @return 是否为整数
     */
    public static boolean isInteger(String s) {
        try {
            Integer.parseInt(s);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    /**
     * 判断对象能否转
     *
     * @param o Object
     * @return 是否为Integer
     */
    public static boolean isInteger(Object o) {
        try {
            Integer.parseInt(String.valueOf(o));
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static String escapeCharacter(String str) {
        if (!isEmpty(str)) {
            if (str.contains("\\")) {
                str = str.replaceAll("\\\\", "\\\\\\\\");
            }
        }
        return str;
    }

    /**
     * @param str
     * @return boolean
     * @Description 匹配字符串是，数字、26个英文字母、下划线组成的8-16位的字符串组合
     * @version 0.1.0
     * @author A80077-刘始达
     * @date 2021/04/06
     * @since 0.1.0
     */
    public static boolean checkPWD(String str) {
        return str.matches("^(?=.*([a-zA-Z].*))(?=.*[0-9].*)[a-zA-Z0-9-_]{8,16}+$");
    }

    /**
     * 判断是否包含特殊字符
     *
     * @param str
     * @return
     */
    public static boolean checkSpecificSymbol(String str) {
        String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]|\n|\r|\t";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.find();
    }

    /**
     * 拼接图片标签url
     *
     * @param str
     * @param ossDomain
     * @return
     */
    public static String replaceHtmlTag(String str, String ossDomain) {
        if (StringUtils.isEmpty(str)) {
            return "";
        }
        if (StringUtils.isEmpty(ossDomain)) {
            return str;
        }
        return replaceHtmlTag(str, "img", "src", "src=\"" + ossDomain, "\"");
    }

    /**
     * html格式处理：替换指定标签的属性和值
     *
     * @param str       需要处理的字符串
     * @param tag       标签名称
     * @param tagAttrib 要替换的标签属性值
     * @param startTag  新标签开始标记
     * @param endTag    新标签结束标记
     * @return
     */
    public static String replaceHtmlTag(String str, String tag, String tagAttrib, String startTag, String endTag) {
        String regxpForTag = "<\\s*" + tag + "\\s+([^>]*)\\s*";
        String regxpForTagAttrib = tagAttrib + "=\\s*\"([^\"]+)\"";
        Pattern patternForTag = Pattern.compile(regxpForTag, Pattern.CASE_INSENSITIVE);
        Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib, Pattern.CASE_INSENSITIVE);
        Matcher matcherForTag = patternForTag.matcher(str);
        StringBuffer sb = new StringBuffer();
        boolean result = matcherForTag.find();
        while (result) {
            StringBuffer stringBuffer = new StringBuffer("<" + tag + " ");
            Matcher matcherForAttrib = patternForAttrib.matcher(matcherForTag.group(1));
            if (matcherForAttrib.find()) {
                String attributeStr = matcherForAttrib.group(1);
                if (!attributeStr.contains("https") && !attributeStr.contains("http")) {
                    matcherForAttrib.appendReplacement(stringBuffer, startTag + attributeStr + endTag);
                }
            }
            matcherForAttrib.appendTail(stringBuffer);
            matcherForTag.appendReplacement(sb, stringBuffer.toString());
            result = matcherForTag.find();
        }
        matcherForTag.appendTail(sb);
        return sb.toString();
    }

    /**
     * @param str
     * @return java.util.Map<String, List < String>>
     * @Description 字符串的连续切割 返回中文词组 数字和字母的集合
     * @version 0.1.0
     * @author 邓彬
     * @date 2021/4/15 13:53
     * @since 0.1.0
     */
    public static Map<String, List<String>> convertStrToChineseList(String str) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        Map<String, List<String>> resultMap = new HashMap<>();
        List<String> chineseList;
        List<String> charList;
        char[] list = str.toCharArray();
        StringBuilder chineseStr = new StringBuilder();
        StringBuilder charStr = new StringBuilder();
        for (char c : list) {
            if (StringUtils.isChinese(c)) {
                chineseStr.append(c);
                charStr.append(Constant.SLASH_MARK_CHARACTER);
            } else if (Character.isLetterOrDigit(c)) {
                charStr.append(c);
                chineseStr.append(Constant.SLASH_MARK_CHARACTER);
            } else {
                charStr.append(Constant.SLASH_MARK_CHARACTER);
                chineseStr.append(Constant.SLASH_MARK_CHARACTER);
            }

        }
        chineseList = Arrays.stream(chineseStr.toString()
                .split(Constant.SLASH_MARK_CHARACTER))
                .filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        charList = Arrays.stream(charStr.toString()
                .split(Constant.SLASH_MARK_CHARACTER))
                .filter(StringUtils::isNotEmpty).map(String::toLowerCase).collect(Collectors.toList());

        resultMap.put("chineseKey", chineseList);
        resultMap.put("charKey", charList);
        return resultMap;
    }

    /**
     * 单个字符转换为小写
     *
     * @param c
     * @return
     */
    public static char singleCharToLowerCase(char c) {
        if (c >= 'A' && c <= 'Z') {
            c += ('a' - 'A');
            return c;
        }
        return c;
    }

    public static boolean isLong(String shopId) {
        try {
            Long.parseLong(shopId);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    public static String priceFormatting(String price) {
        if (StringUtils.isEmpty(price)) {
            return Constant.EMPTY_STRING;
        }

        String newPrice = "";
        // 价格不存在小数点，则直接返回，无需处理
        if (!price.contains(Constant.POINT_BAR_CHARACTER)) {
            newPrice = price;
            return newPrice;
        }

        // 有小数点，则分割字符串
        String[] s = price.split("\\.");

        // 小数位数大于0 且小于2 且存在非0字符
        if (s[1].length() > 0 && s[1].length() <= 2 && !judgeIsNumeric(s[1])) {
            BigDecimal bigDecimal = new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP);
            newPrice = bigDecimal.toPlainString();
        }
        // 【保留这个else if】小数位数大于0 且大于2 且存在非0字符，理论上不会存在，因为新增商品时已经限定最多输入2个小数点
        else if (s[1].length() > 0 && s[1].length() > 2 && !judgeIsNumeric(s[1])) {
            BigDecimal bigDecimal = new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP);
            String[] split = bigDecimal.toPlainString().split("\\.");
            if (split[1].length() > 0 && judgeIsNumeric(split[1])) {
                newPrice = new BigDecimal(bigDecimal.toPlainString()).setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString();
            } else {
                newPrice = bigDecimal.toPlainString();
            }
        } else {
            // 小数位数大于0 且小于2 且小数点都是0
            newPrice = new BigDecimal(price).setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString();
        }
        return newPrice;
    }

    /**
     * 判断字符串是否只包含0
     *
     * @param str
     * @return
     */
    private static boolean judgeIsNumeric(String str) {
        return Pattern.compile("[0]*").matcher(str).matches();
    }

    /**
     * 字符串以","分隔后转为String[]
     *
     * @param s
     * @return
     */
    public static String[] string2ArraySplitByComma(String s) {
        if (s == null || s.length() == 0) {
            return new String[]{};
        }
        return s.split(Constant.COMMA_CHARACTER);
    }

    public static boolean isStringArrayContainsSpecifiedValue(String[] strings, String value) {
        if (null == strings || strings.length <= 0 || value == null || value.length() == 0) {
            return false;
        }
        boolean isContainsSpecifiedValue = false;
        for (String s : strings) {
            if (s.equals(value)) {
                isContainsSpecifiedValue = true;
                break;
            }
        }
        return isContainsSpecifiedValue;
    }

    /**
     * 字符串以","分隔后转为list
     *
     * @param s
     * @return
     */
    public static List<String> string2ListSplitByComma(String s) {
        List<String> stringList = new ArrayList<>();
        if (s == null || s.length() == 0) {
            return stringList;
        }
        String[] strArray = string2ArraySplitByComma(s);

        for (String st : strArray) {
            if (null != st && st.trim() != null || st.trim().length() != 0) {
                stringList.add(st.trim());
            }
        }

        return stringList;
    }

    /**
     * 字符串按照特殊符号
     * ".*[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*()——+|{}【】‘；：”“’。，、？\\\\]+.*"
     * 截取转成字符串集合
     *
     * @param str
     * @return
     */
    public static List<String> splitStringBySpecificSymbol(String str) throws PatternSyntaxException {
        String regEx = "[`~!@#$%^&*()\\-+=|{}':;,\\[\\].<>/?！￥…（）—【】‘；：”“’。，、？\\\\]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return Stream.of(m.replaceAll("_").split("_")).map(String::trim).filter(StringUtils::isNotBlank).collect(Collectors.toList());
    }

    /**
     * 将list转为字符串，用逗号隔开
     *
     * @param list
     * @return
     */
    public static String listTransToStr(List<String> list) {
        if (CollectionUtils.isEmpty(list)) return null;
        StringBuilder sb = new StringBuilder();
        list.forEach(x -> {
            sb.append(x);
            sb.append(",");
        });
        String str = sb.toString();
        return str.substring(0, str.length() - 1);
    }

    /**
     * 是否包含中英文
     *
     * @param str
     * @return
     */
    public static boolean checkCnAndEn(String str) {
        String regEx = Constant.CHI_EN_REGEXP;
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.find();
    }


    /**
     * @param code 要隐藏显示的字符串
     * @param head 前面保留的位数
     * @param tail 后面保留的位数
     * @return 处理后的字符串
     */
    public static String getEncryptCode(String code, int head, int tail) {
        int body = code.length() - head - tail;
        String regexVar = "(\\w{%d})(\\w{%d})(\\w{%d})";
        String regex = String.format(regexVar, head, body, tail);
        String bodyPart = code.replaceAll(regex, "$2");
        String bodyEncrypt = bodyPart.replaceAll("\\w", "*");
        String replacement = String.format("$1%s$3", bodyEncrypt);
        return code.replaceAll(regex, replacement);
    }
}
